package com.wangsd.web.weixin.controller;

import com.wangsd.common.component.WxComponentService;
import com.wangsd.common.utils.HttpClientUtils;
import com.wangsd.web.weixin.entity.Follow;
import com.wangsd.web.weixin.service.FollowService;
import com.wangsd.web.weixin.service.WxComponentBindService;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
import me.chanjar.weixin.mp.bean.kefu.WxMpKefuMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import me.chanjar.weixin.mp.config.impl.WxMpDefaultConfigImpl;
import me.chanjar.weixin.open.bean.message.WxOpenXmlMessage;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;

/**
 * 配置微信开放平台controller
 */
@RestController
@RequestMapping("/notify")
@Slf4j
public class WechatNotifyController {


    @Autowired
    WxComponentService wxComponentService;
    @Autowired
    WxComponentBindService wxComponentBindService;
    @Autowired
    FollowService followService;

    /**
     * （第三方平台）接收取消授权通知、授权成功通知、授权更新通知，也用于接收ticket
     *
     * @param requestBody  对应POST请求的数据
     * @param timestamp    时间戳
     * @param nonce        随机数
     * @param encType      加密类型，为aes
     * @param msgSignature 消息体签名，用于验证消息体的正确性
     * @return
     */
    @RequestMapping("/receive_ticket")
    public Object receiveTicket(@RequestBody(required = false) String requestBody, @RequestParam("timestamp") String timestamp,
                                @RequestParam("nonce") String nonce, @RequestParam("signature") String signature,
                                @RequestParam(name = "encrypt_type", required = false) String encType,
                                @RequestParam(name = "msg_signature", required = false) String msgSignature) {
        log.info(
                "\n接收微信请求：[signature=[{}], encType=[{}], msgSignature=[{}],"
                        + " timestamp=[{}], nonce=[{}], requestBody=[\n{}\n] ",
                signature, encType, msgSignature, timestamp, nonce, requestBody);

        if (!StringUtils.equalsIgnoreCase("aes", encType)
                || !wxComponentService.getWxOpenComponentService().checkSignature(timestamp, nonce, signature)) {
            throw new IllegalArgumentException("非法请求，可能属于伪造的请求！");
        }

        // aes加密的消息
        WxOpenXmlMessage inMessage = WxOpenXmlMessage.fromEncryptedXml(requestBody,
                wxComponentService.getWxOpenConfigStorage(), timestamp, nonce, msgSignature);
        log.debug("\n消息解密后内容为：\n{} ", inMessage.toString());
        try {
            String out = wxComponentService.getWxOpenComponentService().route(inMessage);
            log.debug("\n组装回复信息：{}", out);
        } catch (WxErrorException e) {
            log.error("receive_ticket", e);
        }
        return "success";
    }

    /**
     * 接收公众号或小程序消息和事件推送
     *
     * @param requestBody
     * @param appId
     * @param signature
     * @param timestamp
     * @param nonce
     * @param openid
     * @param encType
     * @param msgSignature
     * @return
     */
    @RequestMapping("{appId}/callback")
    public Object callback(@RequestBody(required = false) String requestBody,
                           @PathVariable("appId") String appId,
                           @RequestParam("signature") String signature,
                           @RequestParam("timestamp") String timestamp,
                           @RequestParam("nonce") String nonce,
                           @RequestParam("openid") String openid,
                           @RequestParam("encrypt_type") String encType,
                           @RequestParam("msg_signature") String msgSignature) {
        log.info(
                "\n接收微信请求：[appId=[{}], openid=[{}], signature=[{}], encType=[{}], msgSignature=[{}],"
                        + " timestamp=[{}], nonce=[{}], requestBody=[\n{}\n] ",
                appId, openid, signature, encType, msgSignature, timestamp, nonce, requestBody);
        if (!StringUtils.equalsIgnoreCase("aes", encType)
                || !wxComponentService.getWxOpenComponentService().checkSignature(timestamp, nonce, signature)) {
            throw new IllegalArgumentException("非法请求，可能属于伪造的请求！");
        }

        String out = "";
        // aes加密的消息
        WxMpXmlMessage inMessage = WxOpenXmlMessage.fromEncryptedMpXml(requestBody,
                wxComponentService.getWxOpenConfigStorage(), timestamp, nonce, msgSignature);
        log.debug("\n消息解密后内容为：\n{} ", inMessage.toString());

        if ("subscribe".equals(inMessage.getEvent())) {
            log.info(openid + "关注公众号" + appId);
            if ("wx4fb6d4148a772890".equals(appId)) {
                Map map = new HashMap<>();
                map.put("openid", openid);
                map.put("appid", appId);
                HttpClientUtils.post("http://localhost:50006/api/h5/testSendBak", map, "UTF-8");
            }
            //查询appSecrt
            /*String appSecrt = wxComponentBindService.selectSecrtByAppId(appId);
            if (StringUtils.isNotBlank(appSecrt)) {
                WxMpService wxMpService = new WxMpServiceImpl();
                WxMpDefaultConfigImpl config = new WxMpDefaultConfigImpl();
                config.setAppId(appId);
                config.setSecret(appSecrt);
                wxMpService.setWxMpConfigStorage(config);
                try {
                    WxMpUser wxMpUser = wxMpService.getUserService().userInfo(openid);

                    Follow follow = new Follow();
                    follow.setAppId(appId);
                    follow.setOpenId(openid);
                    follow.setUnionId(wxMpUser.getUnionId());
                    followService.saveOrUpdate(follow);

                } catch (WxErrorException e) {
                    e.printStackTrace();
                }
            }*/
        } else if ("unsubscribe".equals(inMessage.getEvent())) {
            log.info(openid + "取消关注公众号" + appId);
            followService.deleteByAppIdAndOpenId(appId,openid);
        }

        // 全网发布测试用例
        if (StringUtils.equalsAnyIgnoreCase(appId, "wxd101a85aa106f53e", "wx570bc396a51b8ff8")) {
            try {
                if (StringUtils.equals(inMessage.getMsgType(), "text")) {
                    if (StringUtils.equals(inMessage.getContent(), "TESTCOMPONENT_MSG_TYPE_TEXT")) {
                        out = WxOpenXmlMessage.wxMpOutXmlMessageToEncryptedXml(
                                WxMpXmlOutMessage.TEXT().content("TESTCOMPONENT_MSG_TYPE_TEXT_callback")
                                        .fromUser(inMessage.getToUser())
                                        .toUser(inMessage.getFromUser())
                                        .build(),
                                wxComponentService.getWxOpenConfigStorage()
                        );
                    } else if (StringUtils.startsWith(inMessage.getContent(), "QUERY_AUTH_CODE:")) {
                        String msg = inMessage.getContent().replace("QUERY_AUTH_CODE:", "") + "_from_api";
                        WxMpKefuMessage kefuMessage = WxMpKefuMessage.TEXT().content(msg).toUser(inMessage.getFromUser()).build();
                        wxComponentService.getWxOpenComponentService().getWxMpServiceByAppid(appId).getKefuService().sendKefuMessage(kefuMessage);
                    }
                } else if (StringUtils.equals(inMessage.getMsgType(), "event")) {
                    WxMpKefuMessage kefuMessage = WxMpKefuMessage.TEXT().content(inMessage.getEvent() + "from_callback").toUser(inMessage.getFromUser()).build();
                    wxComponentService.getWxOpenComponentService().getWxMpServiceByAppid(appId).getKefuService().sendKefuMessage(kefuMessage);
                }
            } catch (WxErrorException e) {
                log.error("callback", e);
            }
        } else {
            WxMpXmlOutMessage outMessage = wxComponentService.getWxOpenMessageRouter().route(inMessage, appId);
            if (outMessage != null) {
                out = WxOpenXmlMessage.wxMpOutXmlMessageToEncryptedXml(outMessage, wxComponentService.getWxOpenConfigStorage());
            }
        }
        return out;
    }
}

